setwd("d:/PORES Dropbox/Stephen Pettigrew/ranked-choice-voting/replication files/")

require(tidyverse)
require(janitor)
require(rvest)

options(scipen = 9999)

raw <- readRDS("final-data/sf-vote-results.RDS") %>%
  mutate(year = as.numeric(substr(date, 1, 4)))


tmp <- raw %>%
  count(office.type) %>%
  mutate(office.type2 = sprintf("%s\n(n=%s)", office.type, n))
tmp <- tmp[match(c("Federal","Statewide","State\nLegislature","Other\ndistrict offices",
                   "Ballot props","City\n(First round)", "City\n(Final round)"),tmp$office.type),]
raw$office.type <- factor(raw$office.type,
                          levels = tmp$office.type,
                          labels = tmp$office.type2)


raw %>%
  group_by(date, office) %>%
  mutate(multi = any(grepl("last", type)),
         denom = ifelse(grepl("last", type), NA, votes.counted + overvotes),
         denom = zoo::na.locf(denom),
         rej = overvotes / denom) %>%
  ungroup() %>%
  filter(multi) %>%
  arrange(date, office, round) %>%
  select(geography, date, office, type, rej) %>%
  spread(key = type, value = rej)
  



## Graphs ------

avgs <- raw %>%
  group_by(office.type, type, rcv) %>%
  summarize(n = n(),
            avg = mean(rej),
            se = sd(rej) / sqrt(n),
            upper = avg + qnorm(.975)*se,
            lower = avg + qnorm(.025)*se,
            avg.label = sprintf("%.2f%%",avg * 100))
avgs$main.lab <- ""
avgs$main.lab[grepl("State\nLeg", avgs$office.type)] <- "Non-RCV\noffices"
avgs$main.lab[grepl("First", avgs$office.type)] <- "RCV\noffices"




## Fig 5

raw %>%
  
  ggplot() + 
  
  # dots for each election
  geom_point(mapping = aes(x = office.type, 
                           y = rej),
             position = position_dodge(width = .5),
             alpha = .2) + 
  
  # colored bars for each group avg
  geom_errorbar(mapping = aes(ymin = avg, 
                              ymax = avg,
                              x = office.type,
                              color = rcv,
                              width = .25), 
                data = avgs,
                size = .5, # vert thickness
                position = position_dodge(width = .5)) + 
  geom_errorbar(mapping = aes(ymin = lower,
                              ymax = upper,
                              x = office.type,
                              color = rcv,
                              width = .1),
                data = avgs,
                size = .5) +
  geom_text(mapping = aes(y = avg,
                          x = office.type,
                          label = avg.label),
            data = avgs, 
            nudge_x = .37) + 
  
  geom_text(mapping = aes(y = .02,
                          x = office.type,
                          label = main.lab,
                          color = rcv),
            data = avgs,
            show_guide = F, 
            nudge_x = c(0,.5)) +
  
  
  scale_y_continuous("Percent of votes that were rejected",
                     labels = scales::percent_format(.1)) + 
  ggbreak::scale_y_break(breaks = c(.03, .06)) + 
  xlab("") + 
  theme_bw() + 
  scale_color_manual("", values = c("TRUE" = "blue", "FALSE" = "red")) + 
  # scale_y_break has a bug that adds a second y-axis on right. this removes it:
  theme(axis.text.y.right = element_blank(),
        axis.line.y.right = element_blank(),
        axis.ticks.y.right = element_blank()) + 
  theme(legend.position = "n")





## Fig 6

raw %>%
  
  filter(type != "RCV-last round") %>%
  
  ggplot(aes(x = year, y = rej, color = type, group = type)) + 
  geom_point(position = position_dodge(width = .5), alpha = .5) +
  geom_smooth(se = F) + 
  scale_x_continuous("", 
                     breaks = 2007:2022, 
                     minor_breaks = NULL) + 
  scale_y_continuous("Percent of votes that were rejected",
                     labels = scales::percent_format(.1),
                     breaks = seq(0,.03,.005),) + 
  scale_color_manual("", values = c("RCV-first round" = "blue", "Non-RCV" = "red")) + 
  theme_bw() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
